package camera

import (
	"fmt"
	inputparam "learn-opengl/inputParam"
	"learn-opengl/opengl/shader"
	. "learn-opengl/util"

	"github.com/go-gl/glfw/v3.2/glfw"
	"github.com/go-gl/mathgl/mgl32"
)


type Camera struct {
	// 摄像机位置
	CamePos mgl32.Vec3
	// 看的方向向量
	CameFront mgl32.Vec3
	// 人物实际移动方向--防止人物飞天啥的
	CameWFront mgl32.Vec3
	// 向上向量
	CameUp mgl32.Vec3


	Yaw float32
	Pitch float32

	SuperMode bool
}

func NewCamera(pos mgl32.Vec3) *Camera {
	return &Camera{
		CamePos: pos,
		CameFront: mgl32.Vec3{0,0,-1},
		CameUp: mgl32.Vec3{0,1,0},
		CameWFront: mgl32.Vec3{0,0,-1},
		Yaw: -90,
		Pitch: 0,
	}
}


func (c *Camera) SetPro(shader *shader.Shader) {
	p := mgl32.Perspective(Radians(45.0),4.0/3.0,0.1,1000.0)
	// P(p)
	shader.SetUniformMat4f("projection",p)
}

func (c *Camera) SetView(shader *shader.Shader) {
	shader.Bind()
	// 目标位置
	center := c.CamePos.Add(c.CameFront)
	view := mgl32.LookAt(c.CamePos[0],c.CamePos[1],c.CamePos[2],
						center[0],center[1],center[2],
					c.CameUp[0],c.CameUp[1],c.CameUp[2])
	// P(view)
	shader.SetUniformMat4f("view",view)
}

func (c *Camera) GetPos() mgl32.Vec3 {
	return c.CamePos
}
func (c *Camera) GetFront() mgl32.Vec3 {
	return c.CameFront
}

func (c *Camera) SetPos(shader *shader.Shader) {
	shader.SetUnifor3f("viewPos",c.CamePos)
}

func (c *Camera) SetMat(shader *shader.Shader) {
	c.SetView(shader)
	c.SetPro(shader)
}

func (c *Camera) SetUni(shader *shader.Shader) {
	c.SetPos(shader)
	c.SetMat(shader)
}


var preTime float64
func (c *Camera) Upadte(input *inputparam.Inputparam) {
	step := 0.5 * (glfw.GetTime() - preTime)
	preTime = glfw.GetTime()
	if input.Keys[glfw.KeyW] {
		c.CamePos = c.CamePos.Add(c.CameWFront.Mul(float32(step))) 
	}
	if input.Keys[glfw.KeyS] {
		c.CamePos = c.CamePos.Sub(c.CameWFront.Mul(float32(step))) 
	}
	if input.Keys[glfw.KeyA] {
		c.CamePos = c.CamePos.Add(c.CameUp.Cross(c.CameWFront).Normalize().Mul(float32(step)))
	}
	if input.Keys[glfw.KeyD] {
		c.CamePos = c.CamePos.Sub(c.CameUp.Cross(c.CameWFront).Normalize().Mul(float32(step)))
	}
	if input.Keys[glfw.KeyF] {
		c.CamePos = c.CamePos.Add(c.CameUp.Mul(float32(step)))
	}
	if input.Keys[glfw.KeyG] {
		c.CamePos = c.CamePos.Sub(c.CameUp.Mul(float32(step)))
	}
	sensitity := 0.02
	c.Pitch += float32(sensitity) * input.Delte_mouse_Y
	c.Yaw += float32(sensitity) * input.Delte_mouse_X

	if c.Pitch > 89.0 {
		c.Pitch = 89.0
	} 
	if c.Pitch < -89.0 {
		c.Pitch = -89.0
	}

	c.CameFront[0] = Cos(Radians(c.Pitch)) * Cos(Radians(c.Yaw))
	c.CameFront[1] = Sin(Radians(c.Pitch))
	c.CameFront[2] = Cos(Radians(c.Pitch)) * Sin(Radians(c.Yaw))
	c.CameFront.Normalize()
	
	c.CameWFront = c.CameFront
	c.CameWFront[1] = 0
	fmt.Println(c.CameWFront)
	c.CameWFront = c.CameWFront.Normalize()
	input.Clear()
}


